
package msu.ml.data.level2;

import java.io.*;

/**
 * Packet <a href="http://crane.cs.montana.edu/cgi-bin/cvsweb.cgi/mltoolkit/src/msu/ml/data/level2/PacketBase.java">[CVS]</a> represents a packet
 * of Nexrad Level II data.
 *
 * @author Reginald M Mead
 * @version 1.0
 */
public abstract class PacketBase implements IPacket
{
   /**
    * Create a new Packet by reading the next
    * packet of data from the provided input stream.
    *
    * @param stream input stream to read data from
    */
   public PacketBase(Level2InputStream stream)
   {
      ctm = new byte[12];

      if(stream != null)
      {
         try
         {
            stream.readBytes(ctm, 0, 12);
            msgSize = stream.readShort();
            msgChannel = stream.readByte();
            msgType = stream.readByte();
            idSeq = stream.readShort();
            msgDate = stream.readShort();
            msgTime = stream.readInt();
            numSeg = stream.readShort();
            segNum = stream.readShort();
         }
         catch(IOException e)
         {
            System.out.println("PacketBase Error: " + e.getMessage());
            e.printStackTrace();
            System.exit(0);
         }
      }
   }

   private static String formatString = "\n\nSize: %1$d\nChannel: %2$d\nType: %3$d\nID Sequence: %4$d\nDate-Time: %5$s\nSegments: %6$d\nCurrent Segment: %7$d";

   public String toString()
   {
      return String.format(PacketBase.formatString, msgSize, msgChannel,
            msgType, idSeq, Ray.convertJulianToDate(msgDate, msgTime), 
            numSeg, segNum);
   }

   /**
    * Channel Terminal Manager (Data Integrity Check) 
    * 12 Bytes [Unused]
    */
   protected byte[] ctm;

   //Message Header Information
   /** # of half words until end of record */
   protected short msgSize;

   /**
    * Message size is the number of half words
    * until the end of the record.
    *
    * @return message size
    */
   public int getMessageSize()
   {
      return msgSize;
   }

   /** 
    * Type of Message. 
    * <br />
    * [Left Byte] Channel ID
    * <ul>
    * 	<li>0 = Non-Redundant Site </li>
    * 	<li>1 = Redundant Site Channel 1</li>
    * 	<li>2 = Redundant Site Channel 2</li>
    * </ul>
    * [Right Byte] Message Type
    * <ul>
    * 	<li>1 = Digital Radar Data(Reflectivity and/or Doppler)</li>
    * 	<li>2 = RDA Status Data</li>
    * 	<li>3 = Performance / Maintenance Data</li>
    * 	<li>4 = Console Message (RDA to RPG)</li>
    * 	<li>5 = Maintenance Log Data</li>
    * 	<li>6 = RDA Control Commands</li>
    * 	<li>7 = Volume Coverage Pattern</li>
    * 	<li>8 = Clutter Sensor Zones</li>
    * 	<li>9 = Request for Data</li>
    * 	<li>10 = Console Message (RPG to RDA)</li>
    * 	<li>11 = Loop Back Test (RDA to RPG)</li>
    * 	<li>12 = Loop Back Test (RPG to RDA)</li>
    * 	<li>13 = Clutter Filter Bypass Map (RDA to RPG)</li>
    * 	<li>14 = Edited Clutter Filter Bypass Map (RPG to RDA)</li>
    * </ul>
    */
   protected byte msgChannel;
   protected byte msgType;
   /**
    * ID Sequence, 0 - 0x7FFF then rollover back to 0
    */
   public int getMessageType()
   {
      return msgType;
   }

   protected short idSeq;
   /**
    * Modified Julian Date since January 1 1970
    * (Simply the number of days since 01/01/1970)
    */
   protected short msgDate;
   public int getMessageDate()
   {
      return msgDate;
   }

   /**
    * Packet generation time in milliseconds since midnight (UTC)
    */
   protected int msgTime;
   public int getMessageTime()
   {
      return msgTime;
   }

   /**
    * Number of segments in message. Large messages are segmented
    * into multiple packets.
    */
   protected short numSeg;
   /**
    * Current Segment Number
    */
   protected short segNum;

   public abstract double getAtmosphericAttenuation();
   public abstract int getRayTime();
   public abstract int getRayDate();
   public abstract int getUnambiguousRange();
   public abstract double getAzimuth();
   public abstract int getRayNumber();
   public abstract int getRayStatus();
   public abstract double getElevation();
   public abstract int getElevationNumber();
   public abstract int getReflectivityRange();
   public abstract int getReflectivityGateSize();
   public abstract int getReflectivityGates();
   public abstract int getDopplerRange();
   public abstract int getDopplerGates();
   public abstract int getDopplerGateSize();
   public abstract int getSectorNumber();
   public abstract double getSystemCalibration();
   public abstract int getVelocityResolution();
   public abstract int getVolumeCoveragePattern();
   public abstract int getNyquistVelocity();
   public abstract int getSNRThreshold();
   public abstract double [] getReflectivityData();
   public abstract double [] getVelocityData();
   public abstract double [] getSpectrumWidthData();
   public abstract boolean isRadialData();
}
